package com.tcm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcm.common.enums.CachePrefix;
import com.tcm.config.AppProperties;
import com.tcm.entity.*;
import com.tcm.entity.bo.UserCacheBo;
import com.tcm.entity.dto.TestPaperDetailDto;
import com.tcm.entity.dto.TestPaperDto;
import com.tcm.entity.dto.param.TestPaperPageParam;
import com.tcm.entity.resp.PageR;
import com.tcm.entity.vo.TeacherListResult;
import com.tcm.exception.DatabaseOperationException;
import com.tcm.exception.EntityInvalidException;
import com.tcm.mapper.TestPaperDetailMapper;
import com.tcm.service.*;
import com.tcm.mapper.TestPaperMapper;
import com.tcm.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Guqier
* @description 针对表【ts_test_paper(试卷表)】的数据库操作Service实现
* @createDate 2023-08-02 11:32:29
*/
@Service
public class TestPaperServiceImpl extends ServiceImpl<TestPaperMapper, TestPaper> implements TestPaperService{

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private TestPaperDetailMapper testPaperDetailMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private TestPaperShareService testPaperShareService;

    @Autowired
    private ExerciseService exerciseService;

    public static final Integer  TEACHER_TEST_PAPER_TYPE = 0;// 教师组卷试卷类型
    public static final Integer  SYSTEM_TEST_PAPER_TYPE = 1;// 系统组卷试卷类型

    /**
     * 试卷模块获取教师列表
     * @param currUserId 当前登录用户ID
     * @return 教师列表
     */
    @Override
    public List<TeacherListResult> getTeacherListByTestPaper(Long currUserId){
        List<TeacherListResult> results = new ArrayList<>();
        if (!roleService.isAdministrator(currUserId)) {
            // 如果当前登录用户为教师
            // 获取当前登录用户信息
            UserCacheBo userCacheBo = redisUtil.getCacheObject(CachePrefix.PC_USER_TOKEN.getCacheKey(String.valueOf(currUserId)));
            Teacher teacher1 = teacherService.getTeacherByAccount(userCacheBo.getAccount());
            TeacherListResult teacherListResult = new TeacherListResult();
            BeanUtils.copyProperties(teacher1, teacherListResult);
            results.add(teacherListResult);
        }else {
            // 如果当前登录用户为管理员，则可以获得所有教师列表
            results.addAll(teacherService.getTeacherList());
        }
        return results;
    }

    /**
     * 添加试卷
     * @param dto 试卷数据封装类
     * @param currUserId 当前登录用户ID
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean addTestPaper(TestPaperDto dto, Long currUserId){
        Teacher teacher = teacherService.getById(dto.getTeacherId());
        // 教师信息不存在
        if (teacher == null){
            return false;
        }

        // 构造试卷对象
        TestPaper testPaper = new TestPaper();
        testPaper.setTeacherId(teacher.getId());
        testPaper.setTitle(dto.getTitle());
        testPaper.setType(TEACHER_TEST_PAPER_TYPE);
        testPaper.setCreateUser(currUserId);
        testPaper.setUpdateUser(currUserId);
        boolean saved = this.save(testPaper);

        // 构造试卷详细对象
        int cnt = 0;// 用于计数
        List<TestPaperDetailDto> details = dto.getDetails();
        for (TestPaperDetailDto detailDto : details) {
            TestPaperDetail detail = new TestPaperDetail();
            detail.setTestPaperId(testPaper.getId());
            detail.setType(detailDto.getType());
            detail.setItemId(detailDto.getItemId());
            detail.setSequence(detailDto.getSequence());
            detail.setCreateUser(currUserId);
            detail.setUpdateUser(currUserId);
            if (detailDto.getType().equals(AppProperties.ITEM_TYPE_CLOZE) && !StringUtils.hasText(detailDto.getRank())){
                throw new EntityInvalidException("填空题缺少难易级别");
            }
            detail.setRank(detailDto.getRank());
            if (testPaperDetailMapper.insert(detail) == 1) {
                cnt ++;
            }
        }

        // 检验结果
        if (!saved || cnt != details.size()){
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 修改试卷信息
     * @param dto 试卷数据dto
     * @param currUserId 当前登录用户ID
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean modifyTestPaper(TestPaperDto dto, Long currUserId){
        // 校验试卷是否存在
        TestPaper testPaper = this.getById(dto.getId());
        if (testPaper == null){
            return false;
        }

        // 检验教师是否更换
        if (!testPaper.getTeacherId().equals(dto.getTeacherId())) {
            Teacher teacher = teacherService.getById(dto.getTeacherId());
            if (teacher == null) {
                throw new EntityInvalidException("教师不存在");
            }
            testPaper.setTeacherId(teacher.getId());
        }

        // 更新试卷信息
        testPaper.setTitle(dto.getTitle());
        boolean updated = this.updateById(testPaper);

        // 更新试卷详细信息
        // 删除旧纪录
        LambdaQueryWrapper<TestPaperDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestPaperDetail::getTestPaperId, testPaper.getId());
        Integer count = testPaperDetailMapper.selectCount(queryWrapper);
        int deleted = testPaperDetailMapper.delete(queryWrapper);
        // 插入新记录
        List<TestPaperDetailDto> details = dto.getDetails();
        int cnt = 0;// 用于计数
        for (TestPaperDetailDto detailDto : details) {
            TestPaperDetail detail = new TestPaperDetail();
            detail.setTestPaperId(testPaper.getId());
            detail.setType(detailDto.getType());
            detail.setItemId(detailDto.getItemId());
            detail.setSequence(detailDto.getSequence());
            detail.setCreateUser(currUserId);
            detail.setUpdateUser(currUserId);
            if (detailDto.getType().equals(AppProperties.ITEM_TYPE_CLOZE) && !StringUtils.hasText(detailDto.getRank())){
                throw new EntityInvalidException("填空题缺少难易级别");
            }
            detail.setRank(detailDto.getRank());
            if (testPaperDetailMapper.insert(detail) == 1) {
                cnt ++;
            }
        }

        // 检验结果
        if (!updated || count != deleted || cnt != details.size()){
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 删除试卷
     * @param id 试卷ID
     * @param currUserId 当前登录用户ID
     * @return 处理结果，true为成功
     */
    @Override
    @Transactional
    public boolean removeTestPaper(Long id, Long currUserId){
        // 校验试卷是否存在
        TestPaper testPaper = this.getById(id);
        if (testPaper == null) {
            return false;// 试卷不存在
        }

        // 校验试卷是否被发布
        List<Exercise> exerciseList = exerciseService.list(new LambdaQueryWrapper<Exercise>().eq(Exercise::getTestPaperId, id));
        if (!CollectionUtils.isEmpty(exerciseList)) {
            throw new EntityInvalidException("试卷已被发布，删除失败");
        }

        // 删除试卷实体
        testPaper.setUpdateUser(currUserId);
        this.updateById(testPaper);
        boolean removeById = this.removeById(id);

        // 删除试卷详细
        LambdaQueryWrapper<TestPaperDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestPaperDetail::getTestPaperId, id);
        Integer count = testPaperDetailMapper.selectCount(queryWrapper);
        int delete = testPaperDetailMapper.delete(queryWrapper);

        // 删除试卷分享
        LambdaQueryWrapper<TestPaperShare> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(TestPaperShare::getTestPaperId, testPaper.getId());
        Integer count1 = testPaperShareService.getBaseMapper().selectCount(queryWrapper1);
        int delete1 = testPaperShareService.getBaseMapper().delete(queryWrapper1);

        // 校验结果
        if (!removeById || delete != count || delete1 != count1){
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 根据角色分页获取试卷列表
     * @param param 分页查询参数
     * @param currUserId 当前登录用户ID
     * @return 试卷列表
     */
    @Override
    public PageR<TestPaperDto> getTestPaperByRole(TestPaperPageParam param, Long currUserId){
        Page<TestPaper> page = new Page<>(param.getPage(), param.getPageSize());
        page.addOrder(OrderItem.desc("update_time"));
        LambdaQueryWrapper<TestPaper> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(param.getTitle()), TestPaper::getTitle, param.getTitle());
        // 判断是否是管理员
        if (!roleService.isAdministrator(currUserId)) {
            // 如果是教师则返回当前教师试卷信息
            UserCacheBo userCacheBo = redisUtil.getCacheObject(CachePrefix.PC_USER_TOKEN.getCacheKey(String.valueOf(currUserId)));
            Teacher teacher = teacherService.getTeacherByAccount(userCacheBo.getAccount());
            queryWrapper.eq(TestPaper::getTeacherId, teacher.getId());
        }
        // 如果是管理员则返回全部试卷信息

        // 获取试卷信息
        this.page(page, queryWrapper);
        List<TestPaper> testPapers = page.getRecords();
        // 获取所有试卷详细信息
        LambdaQueryWrapper<TestPaperDetail> detailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        detailLambdaQueryWrapper.in(!CollectionUtils.isEmpty(testPapers), TestPaperDetail::getTestPaperId, testPapers.stream().map(TestPaper::getId).collect(Collectors.toList()));
        List<TestPaperDetail> testPaperDetails = testPaperDetailMapper.selectList(detailLambdaQueryWrapper);

        // 构造结果集，并获取试卷详细信息
        PageR<TestPaperDto> pageR = new PageR<>();
        BeanUtils.copyProperties(page, pageR, "records");

        pageR.setRecords(testPapers.stream().map(testPaper -> {
            TestPaperDto testPaperDto = new TestPaperDto();
            BeanUtils.copyProperties(testPaper, testPaperDto, "details");
            // 查找试卷题目
            testPaperDto.setDetails(testPaperDetails.stream().filter(testPaperDetail -> testPaperDetail.getTestPaperId().equals(testPaper.getId())).map(testPaperDetail -> {
                TestPaperDetailDto detailDto = new TestPaperDetailDto();
                BeanUtils.copyProperties(testPaperDetail, detailDto);
                return detailDto;
            }).collect(Collectors.toList()));
            return testPaperDto;
        }).collect(Collectors.toList()));
        return pageR;
    }

    /**
     * 根据试卷ID获取试卷信息
     * @param id 试卷ID
     * @return 试卷信息
     */
    @Override
    public TestPaperDto getTestPaperById(Long id){
        TestPaper testPaper = this.getById(id);
        if (testPaper == null) {
            return null;
        }
        // 获取试卷详细
        LambdaQueryWrapper<TestPaperDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TestPaperDetail::getTestPaperId, testPaper.getId());
        List<TestPaperDetail> testPaperDetails = testPaperDetailMapper.selectList(queryWrapper);
        TestPaperDto testPaperDto = new TestPaperDto();
        BeanUtils.copyProperties(testPaper, testPaperDto, "details");
        // 查找试卷题目
        testPaperDto.setDetails(testPaperDetails.stream().map(testPaperDetail -> {
            TestPaperDetailDto detailDto = new TestPaperDetailDto();
            BeanUtils.copyProperties(testPaperDetail, detailDto);
            return detailDto;
        }).collect(Collectors.toList()));
        return testPaperDto;
    }

}




